﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data.EntityClient;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Security;
using System.Windows;
using System.Windows.Input;
using System.Xml.Linq;
using Analyzer;
using Analyzer.ViewModel;
using Model;

namespace QualityProfileEditor.ViewModel
{
    internal class MainWindowViewModel : ViewModelBase
    {
        #region Lifecycle

        public MainWindowViewModel()
        {
            this.Items = new ObservableCollection<QualityProfileItemViewModel>();
        }

        #endregion Lifecycle

        #region Properties

        public ActualEntities Context { get; private set; }

        public ObservableCollection<QualityProfileItemViewModel> Items { get; private set; }

        #endregion Properties

        #region Commands

        private RelayCommand pBrowseModelCommand;
        public ICommand BrowseModelCommand
        {
            get
            {
                if (pBrowseModelCommand == null)
                    pBrowseModelCommand =
                        new RelayCommand(
                            param =>
                            {
                                Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog();
                                ofd.AddExtension = true;
                                ofd.DefaultExt = ".db3";
                                ofd.Filter = "Adatbázis|*.db3";
                                ofd.FilterIndex = 0;
                                ofd.Title = "Modell tallózása";
                                ofd.ValidateNames = true;
                                ofd.Multiselect = false;
                                ofd.CheckFileExists = true;
                                ofd.CheckPathExists = true;
                                bool? success = ofd.ShowDialog();
                                if (success.HasValue && success.Value == true)
                                {
                                    EntityConnectionStringBuilder builder = new EntityConnectionStringBuilder();
                                    builder.Metadata = "res://*/ActualModel.csdl|res://*/ActualModel.ssdl|res://*/ActualModel.msl";
                                    builder.Provider = "System.Data.SQLite";
                                    builder.ProviderConnectionString = "data source=\"" + ofd.FileName + "\"";
                                    this.Context = new ActualEntities(builder.ConnectionString);
                                    RefreshItems();
                                }
                            }
                        );
                return pBrowseModelCommand;
            }
        }

        private RelayCommand pBrowseQualityProfileCommand;
        public ICommand BrowseQualityProfileCommand
        {
            get
            {
                if (pBrowseQualityProfileCommand == null)
                    pBrowseQualityProfileCommand =
                        new RelayCommand(
                            param =>
                            {
                                Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog();
                                ofd.AddExtension = true;
                                ofd.DefaultExt = ".xml";
                                ofd.Filter = "Office 2003 XML|*.xml";
                                ofd.FilterIndex = 0;
                                ofd.Title = "Minőségi profil tallózása";
                                ofd.ValidateNames = true;
                                ofd.Multiselect = false;
                                ofd.CheckFileExists = true;
                                ofd.CheckPathExists = true;
                                bool? success = ofd.ShowDialog();
                                if (success.HasValue && success.Value == true)
                                {
                                    RefreshItems();
                                    ParseQualityProfileFromXml(ofd.FileName);
                                    this.Context.CalculateQualityProfile();
                                }
                            },
                            param => this.Context != null
                        );
                return pBrowseQualityProfileCommand;
            }
        }

        #endregion Commands

        #region Methods

        private void RefreshItems()
        {
            this.Items.Clear();
            foreach (var item in this.Context.Categories)
            {
                if (this.Context.QualityProfileItems.Where(
                    qpi => qpi.CategoryName.Equals(item.Name)).Count() == 0)
                {
                    this.Context.QualityProfileItems.AddObject(new QualityProfileItem()
                    {
                        CategoryName = item.Name,
                        Weight = 0
                    });
                    this.Context.SaveChanges();
                }
            }
            foreach (var item in this.Context.QualityProfileItems)
            {
                this.Items.Add(new QualityProfileItemViewModel(item, this.Context));
            }
        }

        [Obsolete("Use ParseQualityProfileFormXml instead!", true)]
        private void ParseQualityProfile(string fileName)
        {
            List<string> allLinesOfQP = null;
            #region ReadAllLines
            System.Threading.Thread.CurrentThread.CurrentUICulture = System.Threading.Thread.CurrentThread.CurrentCulture;
            try
            {
                StreamReader sr = new StreamReader(fileName);
                sr.ReadLine();
                var encoding = sr.CurrentEncoding;
                allLinesOfQP =
                    new List<string>(File.ReadAllLines(fileName, encoding));//UTF7-tel működik jól
            }
            catch (IOException ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }
            catch (UnauthorizedAccessException ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }
            catch (SecurityException ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }
            #endregion ReadAllLines

            // Parse questions and answers
            var header = Analyzer.Properties.Resources.ISO9126toFxCop_EffectMatrix
                .Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).First()
                .Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
            Dictionary<string, List<string>> questionsAndAnswers = new Dictionary<string, List<string>>();
            string lastQuestion = null;
            foreach (var qOrA in header)
            {
                if (qOrA.ToLowerInvariant().StartsWith("q:") == true)
                {
                    lastQuestion = qOrA;
                    if (questionsAndAnswers.ContainsKey(qOrA) == false)
                        questionsAndAnswers[qOrA] = new List<string>();
                }
                else if (lastQuestion == null)
                {
                    Trace.TraceWarning("Answer index {0} skipped while no quentions found before!", qOrA);
                }
                else
                {
                    questionsAndAnswers[lastQuestion].Add(qOrA);
                }
            }

            // Parse form
            lastQuestion = null;
            foreach (var line in allLinesOfQP)
            {
                string qOrA = line.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
                if (string.IsNullOrEmpty(qOrA) == true)
                    ;//SKIP
                else if (qOrA.ToLowerInvariant().StartsWith("q:") == true)
                {
                    lastQuestion = qOrA;
                }
                else if (lastQuestion == null)
                    Trace.TraceWarning("Answer index {0} skipped while no quentions found before!", qOrA);
                else
                {
                    int index = -1;
                    int.TryParse(qOrA, out index);
                    if (index < 0)
                    {
                        Debug.Fail("[ParseQualityProfile] index < 0]");
                        break;
                    }
                    string answerValue = questionsAndAnswers[lastQuestion][index];
                    var query = from answer in this.Context.Answers
                                where answer.Question.Value == lastQuestion && answer.Value == answerValue
                                select answer;
                    if (query.Count() > 1)
                    {
                        var answer = query.First();
                        var question = answer.Question;
                        foreach (var a in question.Answers)
                        {
                            a.IsChecked = false;
                        }
                        answer.IsChecked = true;
                        this.Context.SaveChanges();
                    }
                    else
                        Trace.TraceWarning("Question {0} with answer {1} not found!", lastQuestion, qOrA);
                }
            }
            this.Context.SaveChanges();
        }

        private void ParseQualityProfileFromXml(string fileName)
        {
            // Parse questions and answers
            var header = Analyzer.Properties.Resources.ISO9126toFxCop_EffectMatrix
                .Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).First()
                .Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
            Dictionary<string, List<string>> questionsAndAnswers = new Dictionary<string, List<string>>();
            string lastQuestion = null;
            foreach (var qOrA in header)
            {
                if (qOrA.ToLowerInvariant().StartsWith("q:") == true)
                {
                    lastQuestion = qOrA;
                    if (questionsAndAnswers.ContainsKey(qOrA) == false)
                        questionsAndAnswers[qOrA] = new List<string>();
                }
                else if (lastQuestion == null)
                {
                    Trace.TraceWarning("Answer index {0} skipped while no quentions found before!", qOrA);
                }
                else
                {
                    questionsAndAnswers[lastQuestion].Add(qOrA);
                }
            }

            // Load form
            XDocument doc = XDocument.Load(fileName);
            var ss = doc.Root.Name.Namespace;
            var worksheets =
                doc.Root.Elements(ss + "Worksheet");
            var form = worksheets.First(xe => xe.Attribute(ss + "Name").Value.Equals("KérdőívForm"));
            var rows = form.Element(ss + "Table").Elements(ss + "Row");

            // Parse form
            lastQuestion = null;
            string lastQuestionTrimmed = null;
            foreach (var row in rows)
            {
                string qOrA = row.Element(ss + "Cell").Element(ss + "Data").Value;
                if (string.IsNullOrEmpty(qOrA) == true)
                    ;//SKIP
                else if (qOrA.ToLowerInvariant().StartsWith("q:") == true)
                {
                    lastQuestion = qOrA;
                    lastQuestionTrimmed = lastQuestion.Substring(2);
                }
                else if (lastQuestion == null)
                    Trace.TraceWarning("Answer index {0} skipped while no quentions found before!", qOrA);
                else
                {
                    int index = -1;
                    int.TryParse(qOrA, out index);
                    if (index < 0)
                    {
                        Debug.Fail("[ParseQualityProfile] index < 0]");
                        break;
                    }
                    string answerValue = questionsAndAnswers[lastQuestion][index-1];
                    var query = from answer in this.Context.Answers
                                where answer.Question.Value == lastQuestionTrimmed && answer.Value == answerValue
                                select answer;
                    if (query.Count() > 0)
                    {
                        var answer = query.First();
                        var question = answer.Question;
                        foreach (var a in question.Answers)
                        {
                            a.IsChecked = false;
                        }
                        answer.IsChecked = true;
                        this.Context.SaveChanges();
                    }
                    else
                        Trace.TraceWarning("Question {0} with answer {1} not found!", lastQuestion, qOrA);
                }
            }
            this.Context.SaveChanges();
        }

        #endregion Methods
    }
}
